package com.gxuwz.security;

import java.util.Collection;

import org.apache.log4j.Logger;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

/**
 *  决策管理器
 * <p>功能描述：判断用户的权限是否足够
 * @author Timo
 * @date:2018年5月20日
 */
public class MyAccessDecisionManager implements AccessDecisionManager {
	private final Logger log = Logger.getLogger(getClass());

	@Override
	//authentication 参数装载了从数据库中获取的角色数据（主要是 用户-权限Id集合）。这里是从UserDetailsService里的loadUserByUsername方法里的auths对象的值传过来给 authentication 对象
	//configAttributes 装载了请求的url允许的角色数组 （主要是 url--权限id）。这里是从MySecurityMetadataSource里的loadResourceDefine方法里的value对象取出的角色数据赋予给了configAttributes对象
	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		
		log.info("判断用户是否拥有访问此url的权限id");
		if(authentication == null) {
			throw new AccessDeniedException("权限不足！");
		}
		int result = 0;
		//获取认证对象里的角色名，就是UserDetailServiceImpl的loadUserByUsername方法里的auth对象
		Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
		for(ConfigAttribute attribute : configAttributes){
			if(this.supports(attribute)){
				result = -1;
				for(GrantedAuthority authority : authorities){
					//getAttribute()返回的是角色名，getAuthority()返回的也是角色名
					if (attribute.getAttribute().equals(authority.getAuthority())) {
						result = 1;
						return ;
					}
				}
			}
		}
			throw new AccessDeniedException("权限不足！");
	}

	@Override
	public boolean supports(ConfigAttribute attribute) {
		if (attribute != null)
			return true;
		else
			return false;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
